package com.alks.function.service.impl.finance.costcheck;

import com.alks.common.aop.AutoPageAop;
import com.alks.common.data.dto.SysUserTokenDTO;
import com.alks.common.data.thread.UserIdThread;
import com.alks.entity.data.response.ResponseInfo;
import com.alks.entity.exception.ServiceErrorException;
import com.alks.function.data.dto.finance.costcheck.PcCostLotDto;
import com.alks.function.data.dto.finance.costcheck.PcLotHeadDto;
import com.alks.function.data.request.finance.costcheck.LotCostRequest;
import com.alks.function.data.request.finance.costcheck.LotCostUpdateBatchRequest;
import com.alks.function.data.request.finance.costcheck.LotCostUpdateRequest;
import com.alks.function.mapper.finance.costcheck.PcLotCostMapper;
import com.alks.function.service.finance.costcheck.PcLotCostService;
import com.alks.function.service.impl.asyncImpl.LotCostAsyncServiceImpl;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.alibaba.excel.util.StringUtils.isNumeric;

@Service
@Slf4j
public class PcLotCostServiceImpl  implements PcLotCostService {

    @Autowired
    private PcLotCostMapper pcLotCostMappe;


    /**
     * 未完工指令明细
     * @param request
     * @return
     */
    @Override
    @AutoPageAop
    public ResponseInfo getNotCompleteLotDetail(LotCostRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        List<PcLotHeadDto> list = pcLotCostMappe.getNotCompleteLotDetail(companyId,request);

        HashMap map = new HashMap<>();
        PageInfo page = new PageInfo(list);
        map.put("total",page.getTotal());
        map.put("list",list);
        return ResponseInfo.ok(map);
    }

    /**
     * 完工指令明细
     * @param request
     * @return
     */
    @Override
    @AutoPageAop
    public ResponseInfo getCompleteLotDetail(LotCostRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        List<PcCostLotDto> list = pcLotCostMappe.getCompleteLotDetail(companyId,request);

        HashMap map = new HashMap<>();
        PageInfo page = new PageInfo(list);
        map.put("total",page.getTotal());
        map.put("list",list);
        return ResponseInfo.ok(map);
    }

    /**
     * 批量费用更新
     * @param request
     * @return
     */
    @Override
    public ResponseInfo updateCostBatch(LotCostUpdateBatchRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        //已经封账的不能更新
        List<PcCostLotDto> list = pcLotCostMappe.getCompleteLotDetailBatch(companyId,request.getLotNoList());
        Long countFlag = list.stream()
                .filter(pcCostLotDto -> "Y".equals(pcCostLotDto.getCfmFlag()))
                .collect(Collectors.counting());
        if(countFlag > 0){
            throw  new ServiceErrorException(countFlag + "条数据已封账，不能更新，请检查！");
        }
        //输入费用为0
        if (request.getLastFee() == null || request.getLastFee().equals(0) || request.getAdminFee() == null || request.getAdminFee().equals(0)) {
            throw  new ServiceErrorException("输入费用不能为0");
        }
        //输入必须为数值
        boolean a = isNumeric(request.getLastFee());
        boolean n = isNumeric(request.getAdminFee());
        if(!a || !n){
            throw  new ServiceErrorException("输入必须为数值");
        }
        
        int count = pcLotCostMappe.updateCostBatch(companyId,request);
        if(count > 0){
            return ResponseInfo.ok("更新成功");
        }else{
            throw  new ServiceErrorException("更新失败");
        }
    }

    /**
     * 普通更新
     * @param request
     * @return
     */
    @Override
    public ResponseInfo updateCost(LotCostUpdateRequest request) {
        String companyId = UserIdThread.get().getCompanyId();
        if(request == null){
            throw  new ServiceErrorException("请选择数据！");
        }

        //已经封账的不能更新
        List<PcCostLotDto> list = pcLotCostMappe.getCompleteLotDetailBatch(companyId, Collections.singletonList(request.getLotNo()));
        Long countFlag = list.stream()
                .filter(pcCostLotDto -> "Y".equals(pcCostLotDto.getCfmFlag()))
                .collect(Collectors.counting());
        if(countFlag > 0){
            throw  new ServiceErrorException(countFlag + "条数据已封账，不能更新，请检查！");
        }
        //输入费用为0
        if (request.getLastFee() == null || request.getLastFee().equals(0) || request.getAdminFee() == null || request.getAdminFee().equals(0)) {
            throw  new ServiceErrorException("输入费用不能为0");
        }
        //输入必须为数值
        boolean a = isNumeric(request.getLastFee());
        boolean n = isNumeric(request.getAdminFee());
        if(!a || !n){
            throw  new ServiceErrorException("输入必须为数值");
        }

        int count = pcLotCostMappe.updateCost(companyId,request);
        if(count > 0){
            return ResponseInfo.ok("更新成功");
        }else{
            throw  new ServiceErrorException("更新失败");
        }
    }

    /**
     * 封账批处理
     * @return
     */
    @Override
    public ResponseInfo sealAccount(List<String> lotNoList) {
        String companyId = UserIdThread.get().getCompanyId();
        //判空
        if(lotNoList == null || lotNoList.size() == 0){
            throw  new ServiceErrorException("请选择数据！");
        }
        //已经封装的不能封账
        List<PcCostLotDto> list = pcLotCostMappe.getCompleteLotDetailBatch(companyId,lotNoList);
        Long countFlag = list.stream()
                .filter(pcCostLotDto -> "Y".equals(pcCostLotDto.getCfmFlag()))
                .collect(Collectors.counting());
        if(countFlag > 0){
            throw  new ServiceErrorException(countFlag + "条数据已封账，请检查！");
        }
        //指令成本为0或者null的不能封账
        boolean b = list.stream()
                .anyMatch(pcCostLotDto -> pcCostLotDto.getAmt() == null || pcCostLotDto.getAmt().equals(0));
        if(b){
            throw  new ServiceErrorException("指令成本为0，请检查！");
        }

        LotCostUpdateBatchRequest request = new LotCostUpdateBatchRequest();
        request.setCfmFlag("Y");
        request.setCfmUser(UserIdThread.get().getLoginName());
        request.setCfmDate(new Date());
        request.setLotNoList(lotNoList);
        int count = pcLotCostMappe.updateCostBatch(companyId,request);
        if(count > 0){
            return ResponseInfo.ok("封账成功");
        }else{
            throw  new ServiceErrorException("封账失败");
        }
    }

    /**
     * 取消封账
     * @return
     */
    @Override
    public ResponseInfo cancelSealAccount(List<String> lotNoList) {
        String companyId = UserIdThread.get().getCompanyId();
        //判空
        if(lotNoList == null || lotNoList.size() == 0){
            throw  new ServiceErrorException("请选择数据！");
        }
        //已经封装的不能封账
        List<PcCostLotDto> list = pcLotCostMappe.getCompleteLotDetailBatch(companyId,lotNoList);
        Long countFlag = list.stream()
                .filter(pcCostLotDto -> "Y".equals(pcCostLotDto.getCfmFlag()))
                .collect(Collectors.counting());
        long l = list.size() - countFlag;
        if(l > 0){
            throw  new ServiceErrorException(l + "条数据未封账，请检查！");
        }

        LotCostUpdateBatchRequest request = new LotCostUpdateBatchRequest();
        request.setCfmFlag(null);
        request.setCfmUser(null);
        request.setCfmDate(null);
        request.setLotNoList(lotNoList);
        int count = pcLotCostMappe.updateCostBatchBeNull(companyId,request);
        if(count > 0){
            return ResponseInfo.ok("取消封账成功");
        }else{
            throw  new ServiceErrorException("取消封账失败");
        }
    }

    /**
     * 完工删除
     * @param lotNoList
     * @return
     */
    @Override
    public ResponseInfo deleteCostBatch(List<String> lotNoList) {
        String companyId = UserIdThread.get().getCompanyId();
        //判空
        if(lotNoList == null || lotNoList.size() == 0){
            throw  new ServiceErrorException("请选择数据！");
        }
        //查询数据
        List<PcCostLotDto> list = pcLotCostMappe.getCompleteLotDetailBatch(companyId,lotNoList);
        //已经封账的不能删除
        Long countCfmFlag = list.stream()
                .filter(pcCostLotDto -> "Y".equals(pcCostLotDto.getCfmFlag()))
                .collect(Collectors.counting());
        if(countCfmFlag > 0){
            throw  new ServiceErrorException(countCfmFlag + "条数据已封账，请检查！");
        }
        //是手工插入或没有计算指令成本的能删
        Long countRemark = list.stream()
                .filter(pcCostLotDto -> !("手工插入".equals(pcCostLotDto.getRemark()) && (pcCostLotDto.getAmt()==null || !pcCostLotDto.getAmt().equals(0))))
                .collect(Collectors.counting());
        if(countRemark > 0){
            throw  new ServiceErrorException(countRemark + "条数据不是手工插入或已计算指令成本，请检查！");
        }

        int count = pcLotCostMappe.deleteCostBatch(companyId,lotNoList);
        if(count > 0){
            return ResponseInfo.ok("完工删除成功");
        }else{
            throw  new ServiceErrorException("完工删除失败");
        }
    }

    @Autowired
    private LotCostAsyncServiceImpl lotCostAsyncService;

    /**
     * 插入计算
     * @return
     */
    @Override
    public ResponseInfo addCostBatch(List<PcLotHeadDto> request ,int flag) {
        //判空
        if(request == null || request.size() == 0){
            return ResponseInfo.error("请选择数据！");
        }

        List<PcCostLotDto> pcCostLotDtoList = new ArrayList<>();
        for (PcLotHeadDto dto : request) {
            PcCostLotDto pcCostLotDto = new PcCostLotDto();
            BeanUtils.copyProperties(dto,pcCostLotDto);
            pcCostLotDto.setCompanyId(dto.getCompanyId());
            pcCostLotDto.setOutQtyQs(dto.getOrderQty());
            pcCostLotDto.setJQDate(dto.getDeliveryDate());
            pcCostLotDto.setOutQtyQs(dto.getOutQtyQs());
            pcCostLotDto.setOutDate(dto.getOutDate());
            pcCostLotDto.setSysDate(new Date());
            if(flag == 1){
                SysUserTokenDTO tokenDTO = UserIdThread.get();
                String companyId = tokenDTO.getCompanyId();
                pcCostLotDto.setRemark("手工插入");
                pcCostLotDto.setSysUser(tokenDTO.getUserName());
                pcCostLotDto.setCompanyId(companyId);
            }else{
                pcCostLotDto.setRemark("自动");
                pcCostLotDto.setSysUser("系统账户");
            }
            pcCostLotDtoList.add(pcCostLotDto);
        }

        int count = pcLotCostMappe.addCostBatch(pcCostLotDtoList);
        if(count > 0){
            List<String> list = pcCostLotDtoList.stream().map(PcCostLotDto::getLotNo).collect(Collectors.toList());
            lotCostAsyncService.InsertCalculation(list);
            return ResponseInfo.ok("插入计算批处理成功");
        }else{
            return ResponseInfo.error("插入计算批处理失败");
        }
    }

}
